/**
 * Project: topdt-jbpm
 * Copyright 2013  Top Digital Technology  Co. Ltd.
 * All right reserved.
 */
package com.topdt.jbpm.identity;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import com.topdt.jbpm.model.Activity;
import com.topdt.jbpm.model.ActorDefinDetail;
import com.topdt.jbpm.service.Context;
import com.topdt.jbpm.service.JbpmService;

/**
 * 建立日期 : 2013-4-17 下午2:39:43<br>
 * 作者 : balance<br>
 * 模块 : <br>
 * 描述 : 根据人员定义计算人员<br>
 * 修改历史: 序号 日期 修改人 修改原因 <br>
 * 1 <br>
 * 2 <br>
 */
public class ActorCalculator {

	public static final int DEP_TYPE = 10;// 绝对，部门类型

	public static final int DEP = 1;// 绝对，部门

	public static final int ROLE = 2;// 绝对，角色

	public static final int USER = 0;// 绝对，具体人

	public static final int SWIMLANE = -1;// 泳道（相对）

	public static final int UP = -2;// 上级（相对，处理人的上级）

	public static final int DOWN = -3;// 下级（相对，处理人的下级）

	public static final int RELATIVE_STARTER = -4;// 相对发起人

	public static final int RELATIVE_DELIVER = -5;// 相对提交人

	private static final IdentityService idService = IdFactory.getIdentityServiceFactory().getIdentityService();

	public static List<User> calculate(String activityName, Context context, String doActor) {

		String flowId = context.getFlowId();

		Activity activity = JbpmService.getJbpmService().getActivityDao().getActivityById(flowId, activityName);

		return calculate(activity, context, doActor);
	}

	public static List<User> calculate(Activity activity, Context context, String doActor) {
		List<User> actors = null;
		if (activity.isAbsoluteModel()) {
			actors = ActorCalculator.absoluteCalculate(activity);
		} else if (activity.isRelativeModel()) {
			actors = ActorCalculator.relativeCalculate(activity, context, doActor);
		}
		return actors;
	}

	public static List<User> absoluteCalculate(Activity activity) {

		List<ActorDefinDetail> details = activity.getDetails();

		ActorDefinDetail userDetail = null, roleDetail = null, depDetail = null, depTypeDetail = null;

		for (ActorDefinDetail detail : details) {
			int type = detail.getActorType();

			switch (type) {
			case USER:
				userDetail = detail;
				break;
			case ROLE:
				roleDetail = detail;
				break;
			case DEP:
				depDetail = detail;
				break;
			case DEP_TYPE:
				depTypeDetail = detail;
				break;
			default:
				;
			}
		}

		if (userDetail != null) {
			return calculateByUser(userDetail);
		} else if (depDetail != null) {
			return calculateByDepAndRole(depDetail, roleDetail);

		} else if (depTypeDetail != null) {

			return calculateByDepTypeAndRole(depTypeDetail, roleDetail);
		}
		return null;
	}

	public static List<User> relativeCalculate(Activity activity, Context context, String doActor) {
		List<ActorDefinDetail> details = activity.getDetails();

		List<User> actors = new ArrayList<User>();

		for (ActorDefinDetail detail : details) {

			int type = detail.getActorType();
			switch (type) {
			case SWIMLANE:// 旧处理人
				actors.addAll(calculateSwimlane(detail, context));
				break;
			case RELATIVE_STARTER:// 相对发起人
				actors.addAll(calRelaStarter(detail, context, doActor));
				break;
			case RELATIVE_DELIVER:// 相对提交人
				actors.addAll(calRelaDeliver(detail, context, doActor));
				break;
			case UP:// 旧处理人的上级
				actors.addAll(calculateUp(detail, context));
				break;
			case DOWN:// 旧处理人下级
				actors.addAll(calculateDown(detail, context));
				break;
			default:
				;
			}

		}

		return actors;
	}

	private static List<? extends User> calRelaDeliver(ActorDefinDetail detail, Context context, String doActor) {

		String rId = detail.getActors();

		List<User> users = new ArrayList<User>();

		if (rId != null) {

//			String[] rIds = rId.split(",");
//			for (String r : rIds) {
//
//				String[] r_v = r.split(":");
//
//				int rType = 0;
//				try {
//					rType = Integer.valueOf(r_v[0]);
//				} catch (NumberFormatException e) {
//
//				}
//
//				String rValue = null;
//				if (r_v.length == 2) {
//					rValue = r_v[1];
//				}
//
//				switch (rType) {
//				case 0:// 本人
//					users.addAll(self(doActor));
//					break;
//				case 1:// 本部门负责人
//					users.addAll(depMgrs(doActor, "0"));
//					break;
//				case 2:// 上级部门负责人
//					users.addAll(depMgrs(doActor, rValue));
//					break;
//				case 3:// 本部门其他人员
//					users.addAll(depOthers(doActor));
//					break;
//				case 4:// 下级部门负责人
//					users.addAll(downDepMgrs(doActor));
//					break;
//				case 5:// 下级部门所有人
//					users.addAll(downDepAllPer(doActor));
//					break;
//				}
//
//			}
			
			


				String[] r_v = rId.split("\\|");

				int rType = 0;
				try {
					rType = Integer.valueOf(r_v[0]);
				} catch (NumberFormatException e) {

				}

				String rValue = null;
				if (r_v.length == 2) {
					rValue = r_v[1];
				}

				switch (rType) {
				case 0:// 本人
					users.addAll(self(doActor));
					break;
				case 1:// 本部门负责人
					users.addAll(depMgrs(doActor, "0"));
					break;
				case 2:// 上级部门负责人
					users.addAll(depMgrs(doActor, rValue));
					break;
				case 3:// 本部门其他人员
					users.addAll(depOthers(doActor));
					break;
				case 4:// 下级部门负责人
					users.addAll(downDepMgrs(doActor));
					break;
				case 5:// 下级部门所有人
					users.addAll(downDepAllPer(doActor));
					break;
				case 6:// 提交人部门指定角色zhangyong 20141114
					Department department = idService.getMajorDepOfUser(doActor);	
					List <String> deptIdS = new ArrayList<String>();
					List<Department> deptList = idService.getDepsOfUser(doActor);//本部门加兼职部门
					String [] deptIdArray = new String[deptList.size()];
					for(Department dept:deptList){
						int i = deptList.indexOf(dept);
						deptIdArray[i]= dept.getId();
					}
					List<? extends User> users_ = idService.getUsersByRoleAndDep(rValue.split(",") ,deptIdArray);
					if(users_!=null){
						users.addAll(users_);
					}
					
					break;					
					
				}

		

		} else
			return idService.getManagersByUser(doActor, "0");
		return users;
	}
	/**
	 * 相对发起人
	 * @author 
	 * @date   
	 * @param detail
	 * @param context
	 * @param doActor
	 * @return
	 */
	private static List<? extends User> calRelaStarter(ActorDefinDetail detail, Context context, String doActor) {
		String starter = null;
		if (context != null)
			starter = context.getStarter();

		starter = starter == null ? doActor : starter;

		String rId = detail.getActors();//得到处理人

		List<User> users = new ArrayList<User>();

		if (rId != null) {

//			String[] rIds = rId.split(",");
//			for (String r : rIds) {
//
//				String[] r_v = r.split(":");
//
//				int rType = 0;
//				try {
//					rType = Integer.valueOf(r_v[0]);
//				} catch (NumberFormatException e) {
//
//				}
//
//				String rValue = null;
//				if (r_v.length == 2) {
//					rValue = r_v[1];
//				}
//
//				switch (rType) {
//				case 0:// 本人
//					users.addAll(self(starter));
//					break;
//				case 1:// 本部门负责人
//					users.addAll(depMgrs(starter, "0"));
//					break;
//				case 2:// 上级部门负责人
//					users.addAll(depMgrs(starter, rValue));
//					break;
//				case 3:// 本部门其他人员
//					users.addAll(depOthers(starter));
//					break;
//				case 4:// 下级部门负责人
//					users.addAll(downDepMgrs(starter));
//					break;
//				case 6:// 下级部门所有人
//					users.addAll(downDepAllPer(starter));
//					break;
//				}
//
//			}


				String[] r_v = rId.split("\\|");

				int rType = 0;
				try {
					rType = Integer.valueOf(r_v[0]);
				} catch (NumberFormatException e) {

				}

				String rValue = null;
				if (r_v.length == 2) {
					rValue = r_v[1];
				}

				switch (rType) {
				case 0:// 本人
					users.addAll(self(starter));
					break;
				case 1:// 本部门负责人
					users.addAll(depMgrs(starter, "0"));
					break;
				case 2:// 上级部门负责人
					users.addAll(depMgrs(starter, rValue));
					break;
				case 3:// 本部门其他人员
					users.addAll(depOthers(starter));
					break;
				case 4:// 下级部门负责人
					users.addAll(downDepMgrs(starter));
					break;
				case 5:// 发起人部门指定角色zhangyong 20141113
					Department department = idService.getMajorDepOfUser(starter);		//本部门
					
					List <String> deptIdS = new ArrayList<String>();
					List<Department> deptList = idService.getDepsOfUser(starter);//本部门加兼职部门
					String [] deptIdArray = new String[deptList.size()];
					for(Department dept:deptList){
						int i = deptList.indexOf(dept);
						deptIdArray[i]= dept.getId();
					}
					List<? extends User> users_ = idService.getUsersByRoleAndDep(rValue.split(",") ,deptIdArray);
					if(users_!=null){
						users.addAll(users_);
					}
					
					break;
				case 6:// 下级部门所有人
					users.addAll(downDepAllPer(starter));
					break;
				}

		} else
			return idService.getManagersByUser(starter, "0");
		return users;
	}
	
	private static List<? extends User> downDepAllPer(String userId) {
		return idService.getDownDepsByUser(userId);
	}
	
	private static List<? extends User> downDepMgrs(String userId) {
		return idService.getDownDepMgrs(userId);
	}

	private static List<? extends User> depOthers(String userId) {
		return idService.getOthersOfDep(userId);
	}

	private static List<User> self(String userId) {
		User self = idService.getUserById(userId);
		List<User> users = new ArrayList<User>();
		users.add(self);
		return users;
	}

	private static List<? extends User> depMgrs(String userId, String level) {
		return idService.getManagersByUser(userId, level);
	}

	private static List<User> calculateSwimlane(ActorDefinDetail detail, Context context) {

		String activityName = detail.getActors();
		Map<String, List<User>> hisUsers = context.getHistoryUsers();

		List<User> users = hisUsers.get(activityName);//TODO 有问题

		return users;
	}

	private static List<User> calculateUp(ActorDefinDetail detail, Context context) {
		String userId = detail.getActors();
		return idService.getSuperiors(userId);
	}

	private static List<User> calculateDown(ActorDefinDetail detail, Context context) {
		String userId = detail.getActors();
		return idService.getJuniors(userId);
	}

	private static List<User> calculateByUser(ActorDefinDetail detail) {
		List<User> actors = null;
		String userIdsStr = detail.getActors();
		if (userIdsStr != null) {
			String[] userIds = userIdsStr.split("[,，]");
			actors = new ArrayList<User>();
			actors.addAll(idService.getUsersByUserIds(userIds));//zhangyong 20141116 一次查询所有人			
		}

		return actors;
	}

	private static List<User> calculateByDepAndRole(ActorDefinDetail depDetail, ActorDefinDetail roleDetail) {
		String depS = depDetail.getActors();
		String roleS = roleDetail.getActors();

		String[] roleIds = roleS.split("[,，]");
		String[] depIds = depS.split("[,，]");

		return idService.getUsersByRoleAndDep(roleIds, depIds);
	}

	private static List<User> calculateByDepTypeAndRole(ActorDefinDetail depTypeDetail, ActorDefinDetail roleDetail) {
		String depTs = depTypeDetail.getActors();

		String roleS = roleDetail.getActors();

		String[] depTIds = depTs.split("[,，]");

		String[] roleIds = roleS.split("[,，]");

		return idService.getUsersByRoleAndDepType(roleIds, depTIds);
	}

	public static void fillName(List<User> users) {
		if (users != null) {
			for (User user : users) {
				String id = user.getId();
				user = idService.getUserById(id);
			}
		}

	}

}
